Figure 1-1: Traditional system service APIs require all applications
to communicate through a central manager with corresponding overhead.
In addition to the overhead of the system-provided layer, another
significant problem with traditional service models is that it is impossible for
the provider to express new, enhanced, or unique capabilities to potential
consumers in a standard fashion. A well-designed traditional service
architecture may provide the notion of different levels of service. (Microsoft's
Open Database Connectivity (ODBC)) API is an example of such an API.)
Applications can count on the minimum level of service, and can determine at
run-time if the provider supports higher levels of service in certain
pre-defined quanta, but the providers are restricted to providing the levels of
services defined at the outset by the API; they cannot readily provide a new
capability and then evangelize consumers to access it cheaply and in a fashion
that fits within the standard model. To take the ODBC example, the vendor of a
database provider intent on doing more than the current ODBC standard permits
must convince Microsoft to revise the ODBC standard in a way that exposes that
vendor's extra capabilities. Thus, traditional service architectures cannot be
readily extended or supplemented in a decentralized fashion.
Traditional service architectures also tend to be limited in their
ability to robustly evolve as services are revised and versioned. The problem
with versioning is one of representing capabilities (what a piece of code can
do) and identity (what a piece of code is) in an interrelated, fuzzy way.
A later version of some piece of code, such as "Code version 2" indicates that
it is like "Code version 1" but different in some way. The problem with
traditional versioning in this manner is that it's difficult for code to
indicate exactly how it differs from a previous version and worse
yet, for clients of that code to react appropriately to new versions—or to not
react at all if they expect only the previous version. The versioning problem
can be reasonably managed in a traditional system when (i) there is only a
single provider of a certain kind of service, (ii) the version number of the
service is checked by the consumer when it binds to the service, (iii) the
service is extended only in an upward-compatible manner—for example,
features can only be added and never removed (a significant restriction as
software evolves over a long period of time)—so that a version N provider will
work with consumers of versions 1 through N-1 as well, and (iv) references to a
running instance of the service are not freely passed around by consumers to
other consumers, all of which may expect or require different versions. But
these kind of restrictions are obviously unacceptable in a multi-vendor,
distributed, modular system with polymorphic service providers.
These problems of service management, extensibility, and versioning have
fed the problems stated earlier. Application complexity continues to increase as
it becomes more and more difficult to extend functionality. Monolithic
applications are popular because it is safer and easier to collect all
interdependent services and the code that uses those services into one package.
Interoperability between applications suffers accordingly, where monolithic
applications are loathe to allow independent agents to access their
functionality and thus build a dependence upon a certain behavior of the
application. Because end users demand interoperability, however, application are
compelled to attempt interoperability, but this leads directly back to the
problem of application complexity, completing a circle of problems that limit
the progress of software development.
Send feedback on this article. Find support options.
© 2001 Microsoft Corporation. All rights reserved. Terms of use.